import os
import json
import logging
import time
from typing import Dict, Any, List
from .base_processor import BaseProcessor
from prompts import (
    # 6个方向一对一对应的Prompt（按新需求命名，需在prompts.py中定义）
    PROMPT_SEEDING_SINGLE_SYSTEM, PROMPT_SEEDING_SINGLE_USER,  # 单品种草
    PROMPT_SEEDING_UNBOXING_SYSTEM, PROMPT_SEEDING_UNBOXING_USER,  # 开箱种草
    PROMPT_SEEDING_VLOG_SYSTEM, PROMPT_SEEDING_VLOG_USER,  # vlog种草
    PROMPT_SEEDING_COLLECTION_SYSTEM, PROMPT_SEEDING_COLLECTION_USER,  # 好物合集
    PROMPT_SEEDING_TUTORIAL_SYSTEM, PROMPT_SEEDING_TUTORIAL_USER,  # 教程干货
    PROMPT_SEEDING_DAILY_SYSTEM, PROMPT_SEEDING_DAILY_USER  # 日常种草
)

# 获取当前模块的日志记录器
from app.utils.logger import get_logger

# 传入当前模块名，获取已配置好的日志器
logger = get_logger(__name__)


class SeedingProcessor(BaseProcessor):
    """种草类处理器（6个方向一对一匹配）"""

    def __init__(self, volcano_client, additional_info=""):
        super().__init__(volcano_client)
        self.additional_info = additional_info  # 补充说明（来自请求体）
        logger.info(f"🎬 SeedingProcessor初始化完成，附加信息: {additional_info}")

    async def process(self, inputs: Dict[str, Any]) -> List[Dict[str, str]]:
        """处理种草类任务：接收参数→匹配方向→调用模型→返回分镜列表"""
        logger.info("🚀 开始处理种草任务")
        process_start = time.time()

        # 1. 提取所有参数（与evaluation保持一致，确保无遗漏）
        product_name = inputs.get("product_name", "")  # 匹配{product_name}
        video_outline = inputs.get("outline", "")  # 匹配{video_outline}
        notice = inputs.get("notice", "")  # 匹配{notice}
        ProductHighlights = inputs.get("ProductHighlights", {})  # 匹配{ProductHighlights}
        expert_style = inputs.get("expert_style", {})  # 匹配{expert_style}
        outline_advice = inputs.get("outline_advice", "")  # 匹配{outline_advice}
        direction = inputs.get("direction", "")  # 匹配方向

        # 记录关键输入参数
        logger.info(f"📋 输入参数解析完成 - 种草方向: {direction}")
        logger.info(f"🏷️ 产品名称: {product_name}")
        logger.info(f"📝 视频大纲长度: {len(video_outline)} 字符")
        logger.info(
            f"🎯 产品亮点数量: {len(ProductHighlights) if isinstance(ProductHighlights, dict) else '非字典类型'}")
        logger.debug(f"专家风格键值: {list(expert_style.keys()) if expert_style else '空'}")
        logger.debug(f"大纲建议: {outline_advice[:100] if outline_advice else '无'}")

        # 输入验证日志
        if not direction:
            logger.error("❌ 种草方向为空，无法匹配分支")
            return [{"error": "direction参数为空，无法确定种草方向"}]
        if not product_name:
            logger.warning("⚠️ 产品名称为空，可能会影响生成质量")
        if not video_outline:
            logger.warning("⚠️ 视频大纲为空，可能会影响生成质量")

        logger.info("🔄 开始调用模型处理...")

        # 2. 根据方向匹配对应的模型和Prompt
        result = await self.select_and_call_model(
            direction=direction,
            product_name=product_name,
            video_outline=video_outline,
            notice=notice,
            ProductHighlights=ProductHighlights,
            expert_style=expert_style,
            outline_advice=outline_advice
        )

        # 记录处理结果
        process_time = time.time() - process_start
        if result and not (len(result) == 1 and "error" in result[0]):
            logger.info(f"✅ 种草任务处理成功 - 方向: {direction}, 总耗时: {process_time:.2f}s")
            logger.debug(f"生成分镜数量: {len(result)}")
        else:
            logger.error(f"❌ 种草任务处理失败 - 方向: {direction}")

        # 3. 返回分镜列表（与evaluation处理器保持一致）
        return result

    async def select_and_call_model(
            self, direction, product_name, video_outline, notice,
            ProductHighlights, expert_style, outline_advice
    ):
        """6个种草方向一对一匹配：每个方向对应独立的System Prompt和User Prompt"""
        logger.info(f"🎯 选择模型处理方向: {direction}")
        model_call_start = time.time()

        try:
            # 序列化复杂参数（处理dict/list类型，避免格式化错误）
            highlights_str = json.dumps(ProductHighlights, ensure_ascii=False) if isinstance(ProductHighlights,
                                                                                             (dict, list)) else str(
                ProductHighlights)
            style_str = json.dumps(expert_style, ensure_ascii=False) if isinstance(expert_style, (dict, list)) else str(
                expert_style)

            # 记录提示词构建信息
            logger.debug(f"构建提示词 - 产品名称: {product_name}")
            logger.debug(f"构建提示词 - 视频大纲长度: {len(video_outline)}")
            logger.debug(f"构建提示词 - 产品亮点长度: {len(highlights_str)}")
            logger.debug(f"构建提示词 - 专家风格长度: {len(style_str)}")

            model_response = None

            # 1. 单品种草：独立Prompt
            if direction == "单品种草":
                logger.info("🌱 处理单品种草内容")
                user_prompt = PROMPT_SEEDING_SINGLE_USER.format(
                    product_name=product_name,
                    video_outline=video_outline,
                    notice=notice,
                    ProductHighlights=highlights_str,
                    expert_style=style_str,
                    outline_advice=outline_advice,
                    additional_info=self.additional_info
                )
                logger.debug(f"单品种草提示词长度: {len(user_prompt)}")
                model_response = await self.call_model(
                    system_prompt=PROMPT_SEEDING_SINGLE_SYSTEM,
                    user_prompt=user_prompt
                )

            # 2. 开箱种草：独立Prompt
            elif direction == "开箱种草":
                logger.info("📦 处理开箱种草内容")
                user_prompt = PROMPT_SEEDING_UNBOXING_USER.format(
                    product_name=product_name,
                    video_outline=video_outline,
                    notice=notice,
                    ProductHighlights=highlights_str,
                    expert_style=style_str,
                    outline_advice=outline_advice,
                    additional_info=self.additional_info
                )
                logger.debug(f"开箱种草提示词长度: {len(user_prompt)}")
                model_response = await self.call_model(
                    system_prompt=PROMPT_SEEDING_UNBOXING_SYSTEM,
                    user_prompt=user_prompt
                )

            # 3. vlog种草：独立Prompt（原"vlog植入"改为"vlog种草"，对齐新方向）
            elif direction == "vlog种草":
                logger.info("🎥 处理vlog种草内容")
                user_prompt = PROMPT_SEEDING_VLOG_USER.format(
                    product_name=product_name,
                    video_outline=video_outline,
                    notice=notice,
                    ProductHighlights=highlights_str,
                    expert_style=style_str,
                    outline_advice=outline_advice,
                    additional_info=self.additional_info
                )
                logger.debug(f"vlog种草提示词长度: {len(user_prompt)}")
                model_response = await self.call_model(
                    system_prompt=PROMPT_SEEDING_VLOG_SYSTEM,
                    user_prompt=user_prompt
                )

            # 4. 好物合集：独立Prompt
            elif direction == "好物合集":
                logger.info("🛍️ 处理好物合集内容")
                user_prompt = PROMPT_SEEDING_COLLECTION_USER.format(
                    product_name=product_name,
                    video_outline=video_outline,
                    notice=notice,
                    ProductHighlights=highlights_str,
                    expert_style=style_str,
                    outline_advice=outline_advice,
                    additional_info=self.additional_info
                )
                logger.debug(f"好物合集提示词长度: {len(user_prompt)}")
                model_response = await self.call_model(
                    system_prompt=PROMPT_SEEDING_COLLECTION_SYSTEM,
                    user_prompt=user_prompt
                )

            # 5. 教程干货：独立Prompt（原3个教程方向合并为1个，一对一）
            elif direction == "教程干货":
                logger.info("📚 处理教程干货内容")
                user_prompt = PROMPT_SEEDING_TUTORIAL_USER.format(
                    product_name=product_name,
                    video_outline=video_outline,
                    notice=notice,
                    ProductHighlights=highlights_str,
                    expert_style=style_str,
                    outline_advice=outline_advice,
                    additional_info=self.additional_info
                )
                logger.debug(f"教程干货提示词长度: {len(user_prompt)}")
                model_response = await self.call_model(
                    system_prompt=PROMPT_SEEDING_TUTORIAL_SYSTEM,
                    user_prompt=user_prompt
                )

            # 6. 日常种草：独立Prompt
            elif direction == "日常种草":
                logger.info("🏠 处理日常种草内容")
                user_prompt = PROMPT_SEEDING_DAILY_USER.format(
                    product_name=product_name,
                    video_outline=video_outline,
                    notice=notice,
                    ProductHighlights=highlights_str,
                    expert_style=style_str,
                    outline_advice=outline_advice,
                    additional_info=self.additional_info
                )
                logger.debug(f"日常种草提示词长度: {len(user_prompt)}")
                model_response = await self.call_model(
                    system_prompt=PROMPT_SEEDING_DAILY_SYSTEM,
                    user_prompt=user_prompt
                )

            # 未知方向：返回明确错误
            else:
                logger.error(f"❌ 未知的种草方向: {direction}")
                return [{
                    "景别": "错误",
                    "画面": f"未知种草方向：{direction}",
                    "口播": "请选择正确的种草方向",
                    "花字": "方向错误",
                    "时长": "0",
                    "备注": "支持的方向：单品种草、开箱种草、vlog种草、好物合集、教程干货、日常种草"
                }]

            # 记录模型响应信息
            if model_response and not model_response.startswith('{"error_type"'):
                logger.info(f"🤖 模型调用成功，响应长度: {len(model_response)}")
                logger.debug(f"模型响应前500字符: {model_response[:500]}...")
            elif model_response:
                logger.warning(f"⚠️ 模型返回错误响应: {model_response}")

            # 解析模型返回的JSON结果（调用BaseProcessor的通用解析方法）
            logger.info("🔄 开始解析模型响应JSON")
            parsed_result = self.parse_json_response(model_response)

            if parsed_result and not (len(parsed_result) == 1 and "error" in parsed_result[0]):
                logger.info(f"✅ JSON解析成功，获得 {len(parsed_result)} 个分镜")
            else:
                logger.error(f"❌ JSON解析失败或返回错误")
                logger.debug(f"原始响应内容: {model_response}")

            return parsed_result if parsed_result else [
                {"warning": "模型返回格式异常", "raw_result": model_result[:200]}]

        except Exception as e:
            logger.error(f"💥 模型调用过程中发生异常: {str(e)}", exc_info=True)
            return [{
                "景别": "错误",
                "画面": "处理器异常",
                "口播": str(e),
                "花字": "异常",
                "时长": "0",
                "备注": "种草处理器执行失败"
            }]
        finally:
            logger.debug(f"种草方向匹配+模型调用总耗时: {time.time() - model_call_start:.2f}s")

    def parse_json_response(self, response: str) -> List[Dict[str, str]]:
        """解析分镜列表，修复多JSON块拼接问题"""
        logger.info("🔄 开始解析分镜列表JSON响应")
        try:
            fixed_response = response.strip()

            # 关键修复：先处理多JSON块拼接，再进行其他处理
            # 检测是否存在多个独立的JSON数组（用换行或空格分隔）
            if fixed_response.count('][') > 0:
                # 处理 ]\n[ 或 ][ 的情况
                fixed_response = fixed_response.replace(']\n[', ',').replace('][', ',')
                logger.debug("检测到多JSON块拼接，已修复")

            # 处理多个独立数组的情况（如 "[{...}]\n[{...}]\n[{...}]"）
            elif fixed_response.startswith('[{') and fixed_response.endswith('}]') and '\n' in fixed_response:
                # 移除所有换行，然后替换 "] [" 为 ","
                fixed_response = fixed_response.replace('\n', '').replace('] [', ',')
                # 确保首尾有括号
                if not fixed_response.startswith('['):
                    fixed_response = '[' + fixed_response
                if not fixed_response.endswith(']'):
                    fixed_response = fixed_response + ']'
                logger.debug("检测到多行JSON数组，已合并")

            # 处理日志中显示的具体格式问题："[{...}]\n[{...}]\n[{...}]"
            lines = fixed_response.split('\n')
            if len(lines) > 1 and all(
                    line.strip().startswith('[') and line.strip().endswith(']') for line in lines if line.strip()):
                # 合并所有行的内容
                all_items = []
                for line in lines:
                    line = line.strip()
                    if line:
                        # 移除每个行的方括号，提取内容
                        content = line[1:-1]  # 移除首尾的 [ ]
                        all_items.append(content)
                # 重新组合成单个数组
                fixed_response = '[' + ','.join(all_items) + ']'
                logger.debug(f"检测到多行独立数组，合并为 {len(lines)} 行")

            # 最后尝试通用修复：确保是完整的数组格式
            if fixed_response.startswith('{') and fixed_response.endswith('}'):
                # 如果是单个对象，包装成数组
                fixed_response = '[' + fixed_response + ']'
                logger.debug("单个JSON对象已包装为数组")
            elif not fixed_response.startswith('[') and fixed_response.endswith('}'):
                # 如果缺少开头的 [，但以 } 结尾
                fixed_response = '[' + fixed_response + ']'
                logger.debug("缺少开头括号已修复")
            elif fixed_response.startswith('[') and not fixed_response.endswith(']'):
                # 如果缺少结尾的 ]
                fixed_response = fixed_response + ']'
                logger.debug("缺少结尾括号已修复")

            logger.debug(f"修复后的JSON长度: {len(fixed_response)}")

            parsed = json.loads(fixed_response)

            # 提取分镜列表（与evaluation保持一致）
            if isinstance(parsed, list):
                logger.info(f"✅ 成功解析分镜列表，包含 {len(parsed)} 个分镜")
                return parsed
            if isinstance(parsed, dict):
                for key in ["分镜脚本", "shot_list", "shots", "分镜"]:
                    if key in parsed and isinstance(parsed[key], list):
                        logger.info(f"✅ 成功从字段'{key}'解析分镜列表，包含 {len(parsed[key])} 个分镜")
                        return parsed[key]
                # 单个分镜转为列表
                if all(field in parsed for field in ["镜号", "景别", "画面", "口播"]):
                    logger.info("✅ 成功解析单个分镜并转为列表")
                    return [parsed]

            logger.warning(f"⚠️ 分镜格式不符合预期: {response[:100]}...")
            return [{
                "镜号": 1,
                "景别": "中景",
                "画面": "产品特写",
                "口播": "分镜格式需要调整",
                "花字": "格式异常",
                "时长": "5",
                "备注": "分镜解析格式异常"
            }]

        except json.JSONDecodeError as e:
            logger.error(f"❌ 种草分镜解析失败: {str(e)}")
            logger.debug(f"原始响应内容: {response[:500]}...")
            # 尝试更激进的修复
            try:
                # 移除所有换行和空格，尝试提取JSON对象
                clean_response = response.replace('\n', '').replace(' ', '')
                # 使用正则表达式提取所有 {...} 对象
                import re
                pattern = r'\{[^}]*\}'
                matches = re.findall(pattern, clean_response)
                if matches:
                    # 将所有匹配的对象组合成数组
                    fixed_json = '[' + ','.join(matches) + ']'
                    parsed = json.loads(fixed_json)
                    if isinstance(parsed, list):
                        logger.info(f"✅ 通过正则修复成功，提取到 {len(parsed)} 个分镜")
                        return parsed
            except Exception as fallback_error:
                logger.error(f"💥 备用解析也失败: {str(fallback_error)}")

            return [{
                "镜号": 1,
                "景别": "错误",
                "画面": "JSON解析失败",
                "口播": f"解析错误: {str(e)}",
                "花字": "解析错误",
                "时长": "0",
                "备注": "种草内容JSON格式错误"
            }]